package com.ubxtech.sms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.ubxtech.core.exception.RRException;
import com.ubxtech.core.plugins.Page;
import com.ubxtech.sms.bo.SmsEventBO;
import com.ubxtech.sms.bo.SmsLogBO;
import com.ubxtech.sms.bo.SmsMultiSendBO;
import com.ubxtech.sms.properties.SmsProperties;
import com.ubxtech.sms.req.SmsLogApiReq;
import com.ubxtech.sms.service.SmsPropertiesService;
import com.ubxtech.sms.service.SmsService;
import com.ubxtech.sms.util.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Victor.Xiao
 * @since 2023-05-15 10:46
*/
@Slf4j
@Service
public class SmsServiceImpl implements SmsService {

    @Resource
    private SmsPropertiesService smsPropertiesService;

    /**
     * 批量发送短信
     * @author Victor.Xiao
     * @since 2023-05-15 15:37
     * @param smsEventBO smsEventBO
     * @return java.lang.String
     */
    @Override
    public String batchSendSms(SmsEventBO smsEventBO ) {
        Map<String, Object> requestData = new HashMap<>();
        SmsProperties smsProperties = smsPropertiesService.getSmsConfig();
        checkConfigNull(smsProperties);
        //组合请求数据
        requestData.put("appid", smsProperties.getAppId());
        requestData.put("to", StrUtil.join(",",smsEventBO.getPhoneNumbers()));
        requestData.put("signature", smsProperties.getAppKey());
        requestData.put("content", "【" +smsProperties.getTitle()+"】" + smsEventBO.getContent());
        if (StrUtil.isNotBlank(smsEventBO.getProject()) && smsEventBO.getVars() != null && smsEventBO.getVars().size() > 0) {
            requestData.put("project", smsEventBO.getProject());
            requestData.put("vars", JSONObject.toJSONString(smsEventBO.getVars()));
            return this.request(smsProperties.getApiUrl()+ Constant.BATCH_X_SEND, requestData);
        }
        return this.request(smsProperties.getApiUrl()+ Constant.BATCH_SEND, requestData);

    }

    /**
     * 短信一对多发送
     * @author Victor.Xiao
     * @since 2023-05-15 15:37
     * @param smsEventBO smsEventBO
     * @return java.lang.String
     */
    @Override
    public String multiSendSms(SmsEventBO smsEventBO ) {
        Map<String, Object> requestData = new HashMap<>();
        SmsProperties smsProperties = smsPropertiesService.getSmsConfig();
        checkConfigNull(smsProperties);
        //组合请求数据
        requestData.put("appid", smsProperties.getAppId());
        requestData.put("signature", smsProperties.getAppKey());
        requestData.put("content", "【" +smsProperties.getTitle()+"】" + smsEventBO.getContent());
        requestData.put("multi", JSONArray.toJSONString(smsEventBO.getMulti()));
        if (StrUtil.isNotBlank(smsEventBO.getProject())) {
            requestData.put("project", smsEventBO.getProject());
            return this.request(smsProperties.getApiUrl()+ Constant.MULTI_X_SEND, requestData);
        }
        return this.request(smsProperties.getApiUrl()+ Constant.MULTI_SEND, requestData);

    }

    public static void main(String[] args) {
        String phone = "";
        String appid = "";
        String signature = "";
        SmsEventBO smsEventBO = new SmsEventBO();
        List<SmsMultiSendBO> multi = new ArrayList<>();
        SmsMultiSendBO smsMultiSendBO = new SmsMultiSendBO();
        smsMultiSendBO.setTo(phone);
        JSONObject vars = new JSONObject();
        vars.put("time", "2021年06月10日 14:29:53");
        vars.put("name", "12313");
        vars.put("result", "234");
        vars.put("level", "严重告警");
        smsMultiSendBO.setVars(vars);
        multi.add(smsMultiSendBO);
        smsEventBO.setMulti(multi);
        smsEventBO.setContent("告警时间: @var(time) 告警点位: @var(name) 识别结果: @var(result)告警等级: @var(level)");


        Map<String, Object> requestData = new HashMap<>();
        //组合请求数据
        requestData.put("appid", appid);
        requestData.put("signature", signature);
        requestData.put("content", "【优必选电力后台】" + smsEventBO.getContent());
        requestData.put("multi", JSONArray.toJSONString(smsEventBO.getMulti()));
        HttpRequest httpRequest = HttpRequest.post("https://api-v4.mysubmail.com/sms/multisend");
        HttpResponse response = httpRequest.form(requestData).timeout(10000).execute();
        int status = response.getStatus();
        Assert.isTrue(status == 200, "短信接口请求错误");
        System.out.println(response.body());
    }

    /**
     * 获取模板
     * @author Victor.Xiao
     * @since 2023-05-17 10:31
     * @param templateId templateId
     * @param offset 数据偏移指针 （默认值为0，默认返回最近50个模板信息。offset=1时，查询第51-100个模板， offset=2时，查询第101-150个模板，以此类推。）
     * @return java.lang.String
    */
    @Override
    public String getTemplate(String templateId,String offset ) {
        Map<String, Object> requestData = new HashMap<>();
        SmsProperties smsProperties = smsPropertiesService.getSmsConfig();
        checkConfigNull(smsProperties);
        //组合请求数据
        requestData.put("appid", smsProperties.getAppId());
        requestData.put("signature", smsProperties.getAppKey());
        if (StrUtil.isNotBlank(templateId)) {
            requestData.put("template_id", templateId);
        }
        if (StrUtil.isNotBlank(offset)) {
            requestData.put("offset", offset);
        }
        return this.request(smsProperties.getApiUrl()+ Constant.TEMPLATE, requestData,Method.GET);

    }

    private void checkConfigNull(SmsProperties smsProperties) {
        if (smsProperties == null || StrUtil.isBlank(smsProperties.getApiUrl()) || StrUtil.isBlank(smsProperties.getTitle())
                || StrUtil.isBlank(smsProperties.getAppId()) || StrUtil.isBlank(smsProperties.getAppKey())) {
            throw new RRException("短信参数错误");
        }
    }

    /**
     * 校验appId和key是否能访问
     *
     * @param url  url
     * @param appId  appId
     * @param appKey appKey
     * @return java.lang.Boolean
     * @author Victor.Xiao
     * @since 2023-05-15 18:00
     */
    @Override
    public Boolean checkAppId(String url, String appId, String appKey) {
        Map<String, Object> requestData = new HashMap<>();
        //组合请求数据
        requestData.put("appid", appId);
        requestData.put("signature", appKey);
        String result = this.request(url + Constant.BALANCE_SMS, requestData);
        if (StrUtil.isNotBlank(result)) {
            JSONObject jsonObject = JSONObject.parseObject(result);
            return "success".equalsIgnoreCase(jsonObject.getString("status"));
        }

        return false;
    }

    /**
     * 查询余额
     * @author Victor.Xiao
     * @since 2023-05-15 15:37
     * @return java.lang.String
     */
    @Override
    public String balance() {
        SmsProperties smsProperties = smsPropertiesService.getSmsConfig();
        checkConfigNull(smsProperties);
        Map<String, Object> requestData = new HashMap<>();
        //组合请求数据
        requestData.put("appid", smsProperties.getAppId());
        requestData.put("signature", smsProperties.getAppKey());
        return this.request(smsProperties.getApiUrl()+ Constant.BALANCE_SMS, requestData);

    }


    /**
     * 短信记录
     * @author Victor.Xiao
     * @since 2023-05-16 10:53
     * @param smsLogApiReq smsLogReq
     * @return com.ubxtech.core.plugins.Page<com.ubxtech.sms.bo.SmsLogBO>
     */
    @Override
    public Page<SmsLogBO> smsLog(SmsLogApiReq smsLogApiReq) {
        Page<SmsLogBO> page = new Page<>();
        SmsProperties smsProperties = smsPropertiesService.getSmsConfig();
        checkConfigNull(smsProperties);
        smsLogApiReq.setAppid(smsProperties.getAppId());
        smsLogApiReq.setSignature(smsProperties.getAppKey());
        JSONObject param = JSONObject.parseObject(JSONObject.toJSONString(smsLogApiReq));
        String resultStr = this.request(smsProperties.getApiUrl()+ Constant.SMS_LOG, param);
        if (StrUtil.isBlank(resultStr) || !resultStr.startsWith("{")) {
            log.error("请求短信记录返回结果有误:{}", resultStr);
            return page;
        }
        if (smsLogApiReq.getRows() == null || smsLogApiReq.getRows() == 0) {
            smsLogApiReq.setRows(50);
        }
        if (smsLogApiReq.getOffset() == null ) {
            smsLogApiReq.setOffset(0);
        }
        JSONObject resultJson = JSONObject.parseObject(resultStr);
        page.setTotal(0);
        page.setSize(smsLogApiReq.getRows());
        page.setPages(0);
        page.setCurrent(smsLogApiReq.getOffset() / smsLogApiReq.getRows() == 0 ? 1 : smsLogApiReq.getOffset() / smsLogApiReq.getRows());
        if (!"success".equalsIgnoreCase(resultJson.getString("status"))) {
            log.error("请求短信记录返回status有误:{}", resultStr);
            return page;
        }
        List<SmsLogBO> smsLogBOS = resultJson.getObject("data",new TypeReference<List<SmsLogBO>>(){});
        if (smsLogBOS == null) {
            return page;
        }
        page.setRecords(smsLogBOS);
        page.setTotal(resultJson.getInteger("total"));
//        page.setSize(resultJson.getInteger("results"));
        page.setPages((page.getTotal() % smsLogApiReq.getRows()==0?(page.getTotal() / smsLogApiReq.getRows()):(page.getTotal() / smsLogApiReq.getRows()+1)));
        return page;
    }

    private String request(String url, Map<String, Object> paramMap) {
        return request(url, paramMap, Method.POST);
    }
    private String request(String url, Map<String, Object> paramMap, Method method) {
        SmsProperties smsProperties = smsPropertiesService.getSmsConfig();
        //不发送短信
        if (smsProperties == null || smsProperties.getSwitchFlag() == null || smsProperties.getSwitchFlag() == 0) {
            log.warn("发送短信,模拟成功!,{}", JSONObject.toJSONString(paramMap));
            JSONObject json = new JSONObject();
            json.put("status", "success");
            return json.toJSONString();
        }
        HttpRequest httpRequest = null;
        if (method == Method.GET) {
            httpRequest= HttpRequest.get(url);
        } else {
            httpRequest= HttpRequest.post(url);
        }
//        if (!CollectionUtils.isEmpty(header)) {
//            httpRequest.headerMap(header, true);
//        }
        HttpResponse response = httpRequest.form(paramMap).timeout(10000).execute();
        int status = response.getStatus();
        Assert.isTrue(status == 200, "短信接口请求错误");
        return response.body();
    }



    /**
     * 发送短信
     * @author Victor.Xiao
     * @since 2023-05-15 15:37
     * @param smsEventBO smsEventBO
     * @return java.lang.String
     */
    @Override
    public String sendSms(SmsEventBO smsEventBO ) {
        String result = "";
        if (smsEventBO == null) {
            log.error("监听到发送短信事件,参数为空");
            return result;
        }
        if (log.isDebugEnabled()) {
            log.debug("监听到发送短信事件:{}", smsEventBO);
        }
        //content和project要有一个不能为空
        if (StrUtil.isBlank(smsEventBO.getContent()) && StrUtil.isBlank(smsEventBO.getProject())) {
            log.error("监听到发送短信事件,参数错误:{}", smsEventBO);
            return result;
        }
        if (CollectionUtil.isEmpty(smsEventBO.getPhoneNumbers()) && StrUtil.isBlank(smsEventBO.getPhoneNumber()) && CollectionUtil.isEmpty(smsEventBO.getMulti())) {
            log.error("监听到发送短信事件,号码或者multi为空:{}", smsEventBO);
            return result;
        }
        //批量发送multiSend
        if (smsEventBO.getMulti() != null && smsEventBO.getMulti().size() > 0) {
            result = this.multiSendSms(smsEventBO);
        }
        //一对多 batchSend
        else if (CollectionUtil.isNotEmpty(smsEventBO.getPhoneNumbers()) || StrUtil.isNotBlank(smsEventBO.getPhoneNumber())) {
            result = this.batchSendSms(smsEventBO);
        }

        if (StrUtil.isBlank(result) || !result.contains("success")) {
            log.error("发送短信结果有误,{}", result);
        }
        if (log.isDebugEnabled()) {
            log.debug("发送短信结果:{}", result);
        }
        return result;
    }

}
